﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Net.NetworkInformation;
using System.Net;

namespace PingApp
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        bool goLikeCrazy = false;
        const int maxTTL = 30;
        byte[] magic = ASCIIEncoding.ASCII.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZ\0");
        const int timeOut = 10000;
        int outstandingTasks;
        
        
        public class PingItem
        {
            public string Status { get; set; }
            public int TTL { get; set; }
            public string ReplyHost { get; set; }
            public string ReplyIP { get; set; }
            public long ResponseTime { get; set; }
            public Ping Ping { get; set; }
            public bool Busy { get; set; }
        }

        List<PingItem> list;
        PingItem[] pingItems = new PingItem[maxTTL];
        public PingItem[] PingItems { get { return pingItems; }  }

        private void InitializeRows()
        {

            for(int i = 0; i< maxTTL; i++)
            {
                pingItems[i] = new PingItem();
                pingItems[i].TTL = i + 1;
            }
        }

        public MainWindow()
        {
            InitializeComponent();
            InitializeRows();
            theGrid.ItemsSource = pingItems;
        }

        async void Ping(string url, int ttl)
        {
           // Ping ping = new Ping();
            PingOptions pingOptions = new PingOptions(ttl, true);
            PingReply reply;
            IPHostEntry hostEntry;

            outstandingTasks++;

            if (pingItems[ttl - 1].Ping == null)
            {
                pingItems[ttl - 1].Ping = new Ping();
            }
            else
            {
                if (pingItems[ttl - 1].Busy)
                {
                    pingItems[ttl - 1].Ping.SendAsyncCancel();
                    pingItems[ttl - 1].Busy = false;
                }
            }

            pingItems[ttl - 1].Busy = true;
            reply = await pingItems[ttl - 1].Ping.SendPingAsync(url, timeOut, magic, pingOptions);
            pingItems[ttl - 1].Busy = false;

            pingItems[ttl - 1].Status = reply.Status.ToString();

            if(reply.Status == IPStatus.TtlExpired || reply.Status == IPStatus.Success )
            {
                pingItems[ttl - 1].ReplyIP = reply.Address.ToString();
                pingItems[ttl - 1].ResponseTime = reply.RoundtripTime;
                try
                {
                    pingItems[ttl - 1].ReplyHost = "  <RESOLVING>  ";
                    theGrid.Items.Refresh();
                    hostEntry = await Dns.GetHostEntryAsync(reply.Address);
                    pingItems[ttl - 1].ReplyHost = hostEntry.HostName;
                    theGrid.Items.Refresh();
               
                }
                catch
                {
                    pingItems[ttl - 1].ReplyHost = reply.Address.ToString();
                    theGrid.Items.Refresh();
                }
            }
            else 
            {
                pingItems[ttl - 1].ReplyIP = "n/a";
                pingItems[ttl - 1].ResponseTime = 0;
                pingItems[ttl - 1].ReplyHost = "n/a";
                theGrid.Items.Refresh();            
            }
            outstandingTasks--;
            if(outstandingTasks == 0)
            {
                goButton.IsEnabled = true;
            }
        }

        private void goButton_Click(object sender, RoutedEventArgs e)
        {
           
            goLikeCrazy = true;
            goButton.IsEnabled = false;

            outstandingTasks = 0;
            for (int i = 1; i <= maxTTL; i++)
            {
                pingItems[i - 1].Status = "Busy";
                pingItems[i - 1].ReplyIP = "";
                pingItems[i - 1].ResponseTime = 0;
                pingItems[i - 1].ReplyHost = "";
            }

            theGrid.Items.Refresh();

            for(int i = 1; i <=maxTTL; i++)
            {
                
                Ping(urlBox.Text, i);
            }
        }
    }
}
